#include "logger.h"
#include "cpputils.h"
#include "filechannel.h"

Logger::Logger(const string& name,const string& level): 
    m_name(name),m_running(false),m_console(NULL)
{
    m_cacheQueue = new list<LogMsg*>();
    m_writeQueue = new list<LogMsg*>();
    m_level = parseLevel(level);

    m_thread.start(*this);
}

Logger::~Logger()
{
    m_running = false;
    m_thread.join();

    list<LogMsg*>::iterator it;
    for (it = m_writeQueue->begin(); it != m_writeQueue->end(); ++it)
    {
        delete *it;
    }
    for (it = m_cacheQueue->begin(); it != m_cacheQueue->end(); ++it)
    {
        delete *it;
    }
    delete m_writeQueue;
    delete m_cacheQueue;
    m_writeQueue = NULL;
    m_cacheQueue = NULL;
    
    map<Channel_Type,Channel*>::iterator itCh;
    for( itCh = m_channels.begin(); itCh != m_channels.end(); ++itCh)
    {
        delete itCh->second;
    }

    m_channels.clear();

    if ( m_console != NULL)
    {
        delete m_console;
        m_console = NULL;
    }
}

void Logger::addMsg(LogMsg* plogmsg)
{
    ScopedMutex lock(&m_msgMutex);
    m_cacheQueue->push_back(plogmsg);
}

void Logger::run()
{
    m_running = true;
    list<LogMsg*>::iterator it;
    map<Channel_Type,Channel*>::iterator itCh;
    time_t t1 = time(NULL);
    time_t tnow;
    while(m_running)
    {
        {
            if (m_cacheQueue->empty())
            {
                // 文件滚动检查
                tnow = time(NULL);
                // 滚动的最小时间单位是小时，每分钟更新
                if ( difftime(tnow,t1) >= 60 )
                {
                    itCh = m_channels.find(Channel_Type_File);
                    if ( itCh != m_channels.end() && itCh->second != NULL)
                    {
                        FileChannel* fc = dynamic_cast<FileChannel*>(itCh->second);
                        if (fc != NULL)
                            fc->rotate();
                    }
                    t1 = tnow;
                }
                Thread::sleep(100);
                continue;
            }
            ScopedMutex  lock(&m_msgMutex);
            std::swap(m_writeQueue,m_cacheQueue);
        }
        for (it = m_writeQueue->begin(); it != m_writeQueue->end(); ++it)
        {
            for( itCh = m_channels.begin(); itCh != m_channels.end(); ++itCh)
            {
                LogMsg* pmsg = *it;
                itCh->second->log(*pmsg);
            }
            delete *it;
        }
        m_writeQueue->clear();
    }
}

void Logger::addChannel(Channel* pChannel)
{
    if (pChannel == NULL)
        return;
    
    Channel_Type ct = pChannel->type();
    if (ct == Channel_Type_Console)
    {
        m_console = pChannel;
        return;
    }
    
    map<Channel_Type,Channel*>::iterator itCh;
    itCh = m_channels.find(ct);
    if ( itCh != m_channels.end() && itCh->second != NULL)
    {
        delete itCh->second;
        itCh->second = pChannel;
        return;
    }

    m_channels[ct] = pChannel;
}

void Logger::removeChannel(Channel* pChannel)
{
    if (pChannel == NULL)
        return;
    
    Channel_Type ct = pChannel->type();
    if (ct == Channel_Type_Console && m_console == pChannel)
    {
        delete m_console;
        m_console = NULL;
        return;
    }
    map<Channel_Type,Channel*>::iterator itCh;
    itCh = m_channels.find(ct);
    if ( itCh != m_channels.end())
    {
        delete itCh->second;
        m_channels.erase( itCh);
    }
}

void Logger::setLevel(const string& level)
{
    m_level = parseLevel(level);
}

int Logger::parseLevel(const string& level)
{
    string lowlevel = to_lower(level);
    if (lowlevel == PriorityString[LOG_FATAL])
        return LOG_FATAL;
    else if (lowlevel == PriorityString[LOG_ERROR])
        return LOG_ERROR;
    else if (lowlevel == PriorityString[LOG_WARNING])
        return LOG_WARNING;
    else if (lowlevel == PriorityString[LOG_INFO])
        return LOG_INFO;
    else if (lowlevel == PriorityString[LOG_DEBUG])
        return LOG_DEBUG;
    else if (lowlevel == PriorityString[LOG_TRACE])
        return LOG_TRACE;

    return LOG_TRACE;
}












